part of "../taobao.dart";

/// 自动根据输入的值生成一个可以直接进行request请求的淘宝Uri
/// 1. method为API的接口名称，比如"taobao.open.trades.sold.get"
/// 2. 此函数已经生成了所有的公共参数，因此只需要输入额外的、根据method方法自定义的参数就可以了
Uri getTaobaoUri(
  String method,
  Map<String, String> customParameter,
) {
  // 一、处理parameter
  // 1. 先用method创建一个baseParameter
  final parameter = _baseParameter(method);
  // 2. 在参数中加入自定义参数
  parameter.addAll(customParameter);
  // 3. 在传输之前，对参数进行sign
  parameter._sign(_appSecret);

  // 生成Uri
  return Uri.https("eco.taobao.com", "/router/rest", parameter);
}

/// 无论进行什么请求，都需要先遵守公共参数
Map<String, String> _baseParameter(String method) => {
      "method": method,
      "app_key": _appKey,
      "session": _sessionKey,
      // API协议版本，2.0为淘宝建议的值
      "v": "2.0",
      // 时间戳，客户端和淘宝服务器的时间差不能超过10分钟
      "timestamp": DateTime.now().format("YYYY-MM-DD hh:mm:ss"),
      // 淘宝返回的格式，如果不指定的话会默认为xml
      "format": "json",
      // 防伪签名的格式
      "sign_method": "md5",
    };

extension SignParameters on Map<String, String> {
  /// 淘宝为了防止API被篡改，因此需要在每一次请求之前，融合appSecret和请求的body生成一个独一无二的签名
  /// 具体算法见：https://open.taobao.com/doc.htm?docId=101617&docType=1的第四点
  void _sign(String appSecret) {
    // 将参数按字典顺序排序（淘宝规定）
    var sortedKeys = keys.toList(growable: false)..sort();
    Map<String, String> sortedParameters = {
      for (var k in sortedKeys) k: this[k]!
    };

    // 创建签名字符串
    var signString = '';
    sortedParameters.forEach((k, v) {
      if (k != "" && v != "") {
        signString += "$k$v";
      }
    });

    // 将内容转换为十六进制
    signString = appSecret + signString + appSecret;
    List<int> bytes = utf8.encode(signString);
    var digest = md5.convert(bytes);
    String sign = digest.toString().toUpperCase();

    // 将签名加入到当前Map中
    this["sign"] = sign;
  }
}
